<?php
namespace app\v2\controller;
use think\Db;
use think\Controller;
use app\service\AliSmsService;
use think\facade\Env;
use app\service\WxService;
use think\facade\Log;
# 接入支付
use Yurun\PaySDK\Weixin\Params\PublicParams;
use Yurun\PaySDK\Weixin\SDK;
use Yurun\PaySDK\Weixin\JSAPI\Params\Pay\Request;
use Yurun\PaySDK\Weixin\JSAPI\Params\JSParams\Request as jsRequest;
use think\Exception;

class Index
{
    const PAGESIZE = 5;
    /**
     * 最新版本AI预测 
     */
    public function v3latestPersonPredict()
    {
        $params = input('');
        # 需要展示时间节点预测. personal_consult_show
        $personConsultShow = config('personal_consult_show');
        $personConf = config('personal_consult_tmpl');
        # 大类型
        $type  = isset($params['types']) ? $params['types'] : 0;
        # 大栏目下的 子菜单
        $itypes  = isset($params['itypes']) ? $params['itypes'] : 0;
        # 用户填写的信息
        $personMsg = isset($params['person_fix_msg']) ? $params['person_fix_msg'] : '';
        # 职位. 该字段 仅在工作事业栏目有
        $jobTitle = isset($params['person_job']) ? $params['person_job'] : '';
        # 该参数指的是, 当前咨询对应 的 结果ID
        $id = isset($params['id']) ? $params['id'] : 0;
        $res = ['code' => 0, 'data' => [], 'msg' => ''];
        
        if (empty($type) && empty($id))   exit(json_encode($res, JSON_UNESCAPED_UNICODE));
        
        # 没有ID的情况,根据type取出随机数
        if (empty($id)) {
            # 用户无可用套餐, 不允许咨询
            $userComboInfo = Db::name('member')->field('id,once_nums,month_day')->where(['phone' => $params['user_phone']])->find();            
            
            if ($userComboInfo['once_nums'] <=0 && $userComboInfo['month_day'] <= 0) {
                $res['code'] = 1;
                $res['msg'] = '无可用咨询套餐';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
                exit;                
            }
            # 根据 大小菜单, 确认用户提问信息
            $personTpl = isset($personConf[$type]['items'][$itypes]) ? $personConf[$type]['items'][$itypes] : '';
            
            # 如果是 工作事业选择
            if ($itypes == 4) $personTpl = sprintf($personTpl, $jobTitle, $personMsg);
            # 非工作事业选择
            if ($itypes != 4) $personTpl = sprintf($personTpl, $personMsg);   
            
            # 类型不能为空
            if (empty($type)) {
                $res['code'] = 0;
                $res['msg'] = '咨询类型不能为空!';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
                exit;
            }
            
            # 新增字段
            $phone = (isset($params['user_phone']) && !empty($params['user_phone'])) ? $params['user_phone'] : '';
            # 手机号不能为空
            if (empty($phone)) {
                $res['code'] = 0;
                $res['msg'] = '手机号为必填参数';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
                exit;
            }            
            # 随机取一个. 如果是: 项目预测: 1 + 公关审核
            if ($type == 1 || $type == 4)   $typeIds = Db::name('docs_latest')->field('id')->select();
            # 随机取一个. 如果是: 工作事业选择: 2
            if ($type == 2)   $typeIds = Db::name('docs_works')->field('id')->select();
            # 随机取一个. 如果是: 情感咨询选择: 3
            if ($type == 3)   $typeIds = Db::name('docs_emotion')->field('id')->select();
            
            $typeIdsArr = array_column($typeIds, 'id');
            # 从数组里面随机取出一个
            $key    = array_rand($typeIdsArr);
            $id     = $typeIdsArr[$key];

            $info = [];
            if ($type == 1 || $type == 4)   $info   = Db::name('docs_latest')->field('*')->where(['id' => $id])->find();
            # 随机取一个. 如果是: 工作事业选择: 2
            if ($type == 2)   $info   = Db::name('docs_works')->field('*')->where(['id' => $id])->find();
            # 随机取一个. 如果是: 情感咨询选择: 3
            if ($type == 3)   $info   = Db::name('docs_emotion')->field('*')->where(['id' => $id])->find();            
            # $info   = Db::name('docs_latest')->field('*')->where(['id' => $id])->find();

            # 去除解决方案 字段的空格
            // $info['solution'] =  ltrim($info['solution']);
            # 将当前用户的, 提交记录 存储
            $isShowTimes = in_array($itypes, $personConsultShow['is_show_time_ids']) ? 1 : 0;

            $insertData = [
                'result_id' => $id,
                'user_phone' => $phone,
                'person_menu_id' => $type,
                'person_menu_item_id' => $itypes,
                'person_fix_msg' => $personMsg,
                'person_job' => $jobTitle,
                'is_show_time_res' => $isShowTimes,
                'add_time'=> date('Y-m-d H:i:s', time())
            ];
            $historyId = Db::name('new_user_question_history')->insertGetId($insertData);
            
            $info['is_show_time_res'] = $isShowTimes;
            $info['person_tpl'] = $personTpl;
            $info['history_id'] = $historyId;
            $info['types'] = $type;
            $info['itypes'] = $itypes;
            # 循环数据里面的 每个 value.替换 \n为 <br/>
            if (!empty($info)) {
                foreach ($info as $kItem => $kVal) {
                    $info[$kItem] = str_replace('\n', '<br/>', $info[$kItem]);
                }
            }            
            $res['data'] = $info;
            # TODO: 传入combo_type
            $comboType = isset($params['comboType']) ? $params['comboType'] : 100;
            # 无月卡套餐, 扣减次数.有月卡继续执行
            if ($userComboInfo['month_day'] <= 0) {
                # 用户表扣减次数
                Db::name('member')->where(['phone' => $params['user_phone']])->setDec('once_nums');
                # 次卡套餐表 扣减次数
                Db::name('zifei_combo')->where(['user_phone' => $params['user_phone']])->setDec('use_times');
                Db::name('zifei_combo')->where(['user_phone' => $params['user_phone']])->update(['update_time' => date('Y-m-d H:i:s', time())]);
            }

            # Log::info('提问记录::'. json_encode($insertData, JSON_UNESCAPED_UNICODE));
            
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));
        } else {
            # 个人 咨询,历史记录
            $historyId = isset($params['history_id']) ? $params['history_id'] : 0;
            
            if (empty($historyId)) {
                $res['msg'] = '咨询记录ID不能为空!';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
            }   
            # 根据 $historyId, 得出它咨询所 得到的答案ID
            $historyInfo = Db::name('new_user_question_history')->field('person_fix_msg,person_job,result_id')->where(['id' => $historyId])->find();
            
            $resultId = $id;
            // $resultId = isset($historyInfo['result_id']) ? $historyInfo['result_id'] : 0;

            if (empty($resultId)) {
                $res['msg'] = '未查询到咨询结果!';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));                
            }
            # 根据 大小菜单, 确认用户提问信息
            $personTpl = isset($personConf[$type]['items'][$itypes]) ? $personConf[$type]['items'][$itypes] : '';
            # 如果是 工作事业选择
            if ($itypes == 4) $personTpl = sprintf($personTpl, $historyInfo['person_fix_msg'], $historyInfo['person_job']);
            # 非工作事业选择
            if ($itypes != 4) $personTpl = sprintf($personTpl, $historyInfo['person_fix_msg']);
            
            # 随机取一个. 如果是: 项目预测: 1 + 公关审核
            if ($type == 1 || $type == 4) $info = Db::name('docs_latest')->field('*')->where(['id' => $resultId])->find();
            # 随机取一个. 如果是: 工作事业选择: 2
            if ($type == 2)   $info = Db::name('docs_works')->field('*')->where(['id' => $resultId])->find();
            # 随机取一个. 如果是: 情感咨询选择: 3
            if ($type == 3)   $info = Db::name('docs_emotion')->field('*')->where(['id' => $resultId])->find();
                   
            $info['is_show_time_res'] = 1;
            $info['person_tpl'] = $personTpl;
            $res['code'] = 0;
            # 循环数据里面的 每个 value.替换 \n为 <br/>
            if (!empty($info)) {
                foreach ($info as $kItem => $kVal) {
                    $info[$kItem] = str_replace('\n', '<br/>', $info[$kItem]);
                }
            }
            
            # if (isset($info['twenty_years_predict']))   $info['twenty_years_predict'] = str_replace('\n', '<br/>', $info['twenty_years_predict']);
            $res['data'] = $info;

            exit(json_encode($res, JSON_UNESCAPED_UNICODE));            
        }
        exit;        
    }     
    /**
     * 每天定时执行, 对用户的 非次卡套餐进行扣除 
     */
    public function dailyDecCombo()
    {
        # 获取当天是否执行过 任务
        $dayPrefix = 'cron_'.date('Ymd');
        # 如果当天未执行
        if (!cache($dayPrefix)) {
        //   if (true) {
            // $freeTimes = Db::name('config')->where('id',21)->value('value');
            // 项目咨询类目, 定时任务
            $con[] = ['month_day', '>', 0];
            # 扣减月卡天数
            Db::name('member')->where($con)->setDec('month_day');
            # 为没有次卡的用户设置 免费次卡
            
            // # 工作事业类目, 定时任务
            $con  = [];
            $con[] = ['works_month_nums', '>', 0];
            # 扣减月卡天数
            Db::name('member')->where($con)->setDec('works_month_nums');
            
            # 情感咨询类目, 定时任务
            $con  = [];
            $con[] = ['emotion_month_nums', '>', 0];
            # 扣减月卡天数
            Db::name('member')->where($con)->setDec('emotion_month_nums');
            
            # 公关审核类目, 定时任务
            $con  = [];
            $con[] = ['pr_month_nums', '>', 0];
            # 扣减月卡天数
            Db::name('member')->where($con)->setDec('pr_month_nums');

            # 团体用户套餐, 定时任务
            $con  = [];
            $con[] = ['group_month_nums', '>', 0];
            # 扣减月卡天数
            Db::name('member')->where($con)->setDec('group_month_nums');
            
            Log::info($dayPrefix.'::已执行');
            cache($dayPrefix, 1);
        }

    }
    /**
     * 获取用户套餐 
     */
    public function getUserCombo()
    {
        $res = ['code' => 1, 'data' => [], 'msg' => ''];
        
        try {
            $reqParams = input('');
            # 入单请求参数
            if (empty($reqParams['user_phone']) || !checkPhone($reqParams['user_phone'])) {
                $res['msg'] = '用户唯一凭证格式不正确!';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
            }
            $userComboInfo = Db::name('member')->field('id,once_nums,month_day')->where(['phone' => $reqParams['user_phone']])->find();
            # 获取 单次/月卡的费用
            $oncePay = Db::name('config')->where(['name' => 'oncepay'])->column('value');
            $monthPay = Db::name('config')->where(['name' => 'monpay'])->column('value');
            
            $res['code'] = 0;
            $res['data']['once_nums'] = isset($userComboInfo['once_nums']) ? $userComboInfo['once_nums'] : 0;
            $res['data']['month_day'] = isset($userComboInfo['month_day']) ? $userComboInfo['month_day'] : 0;
            $res['data']['oncepay'] = isset($oncePay[0]) ? $oncePay[0] : 0;
            $res['data']['monpay'] = isset($monthPay[0]) ? $monthPay[0] : 0;
            
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));
        }  catch (Exception $e) {
            $res['msg'] = $e->getMessage();
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));            
        }
    }
    /**
     * 查看用户资费订单 
     */
    public function getFeeOrder()
    {
        $res = ['code' => 1, 'data' => [], 'msg' => ''];
        
        try {
            $reqParams = input('');
            # 入单请求参数
            if (empty($reqParams['user_phone']) || !checkPhone($reqParams['user_phone'])) {
                $res['msg'] = '用户唯一凭证格式不正确!';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
            }
            # 获取用户的付费订单
            $con = [
                'user_phone' => $reqParams['user_phone'],
                'pay_status' => 1    
            ];
            $orderLists = Db::name('zifei_order')->field('id,order_sn,add_time,combo_type,order_amount')->where($con)->order('id', 'desc')->paginate(static::PAGESIZE);
            // $res['data'] = $orderLists->items();
            $res['data'] = $orderLists;
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));
        } catch (Exception $e) {
            $res['msg'] = $e->getMessage();
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));            
        }
    }
    /**
     * 入单接口
     */
    public function intoOrder()
    {
        $res = ['code' => 1, 'data' => [], 'msg' => ''];
        try {
            $reqParams = input('');
            # 入单请求参数
            if (empty($reqParams['user_phone'])) {
                $res['msg'] = '用户唯一凭证为必传标识';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
            }
            
            $comboType = isset($reqParams['combo_type']) ? $reqParams['combo_type'] : -1;
            # 套餐类型: 0-单次咨询,1-包月套餐
            $comboTypeArr = [0, 1];
            $comboTypeName = ['oncepay', 'monpay'];
            
            if (!in_array($comboType, $comboTypeArr)) {
                $res['msg'] = '套餐标识错误';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));            
            }
            # 获取用户openid
            $userInfo = Db::name('member')->where(['phone' => $reqParams['user_phone']])->column('openid');
            $openid = isset($userInfo[0]) ? $userInfo[0] : '';
            
            if (empty($openid)) {
                $res['msg'] = '微信用户标识错误';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));                 
            }
            # 当前用户有 包月套餐, 不允许购买单次套餐(月卡未过期之前不允许购买)
            $hasYearCombo = $this->v2getUserHasCombo($reqParams['user_phone'], $comboType);
            
            if ($hasYearCombo) {
                $res['msg'] = '当前已有包月套餐!';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));                 
            }
            # 根据套餐 类型获取支付金额
            $comboVal = Db::name('config')->where(['name' => $comboTypeName[$comboType]])->column('value');
            
            if (!isset($comboVal[0]) || $comboVal[0] <= 0) {
                $res['msg'] = '套餐资费配置错误';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));              
            }
            
            $amount = $comboVal[0];       
            $content = 'AI分析-咨询服务费';
            $paymentSn = 'AI_' . date('YmdHis').'_'.mt_rand(10000, 99999);
    
            $params = new PublicParams;
            # 微信支付配置
            $wechatPayConf = config('app.wechat_pay');
            # 支付平台分配给开发者的应用ID 
            $params->appID = $wechatPayConf['mini_appid'];
            # 微信支付分配的商户号
            $params->mch_id = $wechatPayConf['mch_id'];
            # 商户API 密钥 
            $params->key = $wechatPayConf['mch_secret'];
            # SDK实例化，传入公共配置
            $pay = new SDK($params);
            # 支付接口（生成支付订单）
            $request = new Request;
            $request->body = $content;
            $request->out_trade_no = $paymentSn;
            # 支付金额 换算成: xx分
            $request->total_fee = $amount*100;
            # $request->spbill_create_ip = '127.0.0.1';
            $request->notify_url = env('app.domain', 'http://docs.spacetimesc.com/').'v2/index/recvNotify';
            $request->openid = $openid;
    
            # 调用接口
            $result = $pay->execute($request);
            if($pay->checkResult())
            {
                $request = new jsRequest;
                $request->prepay_id = $result['prepay_id'];
                $jsapiParams = $pay->execute($request);
                # 增加本次发起支付的订单编号
                $insertData = [
                    'user_phone' => $reqParams['user_phone'],
                    'order_sn' => $paymentSn,
                    'combo_type' => $comboType,
                    'order_amount' => $amount,
                    'add_time' => date('Y-m-d H:i:s', time())
                ];
                $insertRes = Db::name('zifei_order')->insert($insertData);
                
                if (!$insertRes)    throw new Exception('支付系统繁忙,请稍后再试!');
                
                $res['code'] = 0;
                $res['data'] = $jsapiParams;
                
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));           
            } else {
                $res['msg'] = '微信支付,请求失败!';
                exit(json_encode($res, JSON_UNESCAPED_UNICODE));
            }            
        } catch (Exception $e) {
            $res['msg'] = $e->getMessage();
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));            
        }
    }
    /**
     * 回调接口
     */
    public function recvNotify()
    {
        $reqParams = file_get_contents('php://input');
        Log::info('微信支付回调::'. $reqParams);
        # 解析通知的xml
        # $xmlContent = simplexml_load_string($reqParams); 
        $xmlArr = parserXMLToArray($reqParams, 'array');
        # 本站订单号
        $orderSn = isset($xmlArr['out_trade_no']) ? $xmlArr['out_trade_no'] : '';
        $resultCode = isset($xmlArr['result_code']) ? $xmlArr['result_code'] : '';
        $transactionId = isset($xmlArr['transaction_id']) ? $xmlArr['transaction_id'] : '';

        if ($resultCode == 'SUCCESS') {
            # 更新订单信息
            $updateData = [
                'pay_time' => date('Y-m-d H:i:s', time()),
                'pay_status' => 1,
                'transaction_sn' => $transactionId
            ];
            
            # Log::info('订单更新结果::', ['update_res' => true]);
            # 增加用户的套餐次数
            $orderInfo = Db::name('zifei_order')->field('user_phone,combo_type,pay_status')->where(['order_sn' => $orderSn, 'pay_status' => 0])->find();
            
            if (!empty($orderInfo) && isset($orderInfo['combo_type']) && isset($orderInfo['user_phone'])) {
                # 套餐增加的天数, 索引=>套餐类型, 值=>体验的 天数.0下标=>代表次数
                $comboDayArr = [1, 30];
                # 单次增加次数
                if ($orderInfo['combo_type'] == 0) Db::name('member')->where(['phone' => $orderInfo['user_phone']])->setInc('once_nums', $comboDayArr[$orderInfo['combo_type']]);
                # 月套餐以上,增加天数
                if ($orderInfo['combo_type'] == 1) Db::name('member')->where(['phone' => $orderInfo['user_phone']])->setInc('month_day', $comboDayArr[$orderInfo['combo_type']]);
                # 更新订单状态
                Db::name('zifei_order')->where(['order_sn' => $orderSn, 'pay_status' => 0])->update($updateData);
                
                $userComboInfo = Db::name('zifei_combo')->field('id,combo_type')->where(['user_phone' => $orderInfo['user_phone']])->find();
                # 当前用户,已有包月套餐. 入单已判断. 这里再加一层
                if (!empty($userComboInfo) && $userComboInfo['combo_type'] == 1) {
                    Log::info('已存在包月套餐::'.json_encode($userComboInfo, JSON_UNESCAPED_UNICODE));
                    echo 'success';
                    exit;                    
                }
                
                $comboDayArr = [0, 30];
                # 不存在,则新增. 存在: 增加用户的可用次数
                if (empty($userComboInfo)) {
                    $addComboData = [
                        'user_phone' =>  $orderInfo['user_phone'],
                        'combo_type' =>  $orderInfo['combo_type'],
                        'combo_day' => $comboDayArr[$orderInfo['combo_type']],
                        'add_time' => date('Y-m-d H:i:s', time()),
                        'update_time' => date('Y-m-d H:i:s', time()),
                        # 包月套餐不需要该字段
                        'use_times' => ($orderInfo['combo_type'] == 0) ? 1 : 0 
                    ];
                    
                    $insertRes = Db::name('zifei_combo')->insert($addComboData);
                    Log::info('套餐录入成功::');
                } else {
                    # 单次增加次数
                    if ($orderInfo['combo_type'] == 0)  Db::name('zifei_combo')->where(['user_phone' => $orderInfo['user_phone']])->setInc('use_times');
                    # 包月套餐,在增加30天
                    if ($orderInfo['combo_type'] == 1)  Db::name('zifei_combo')->where(['user_phone' => $orderInfo['user_phone']])->setInc('combo_day', $comboDayArr[$orderInfo['combo_type']]);
                    # 更新时间
                    Db::name('zifei_combo')->where(['user_phone' => $orderInfo['user_phone']])->update(['update_time' => date('Y-m-d H:i:s', time())]);
                }
            } else {
                Log::info('未查询到订单详情::', ['order_sn' => $orderSn]);
            }
        }

        echo 'success';
        exit;
    }    
    /**
     * 获取当前用户 是否可以使用 咨询 
     */
    public function v2getUserIsUse()
    {
        $params = input('');
        $res = ['code' => 1, 'data' => [], 'msg' => ''];
        
        if (empty($params['user_phone'])) {
            $res['msg'] = '用户唯一凭证为必传标识';
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));
        }
        # 获取用户是否,有单次购买 & 未使用的套餐
        $userHasCombo = $this->v2getUserHasCombo($params['user_phone']);
        $userHasFree = $this->v2getUserHasFree($params['user_phone']);

        # 获取单次付费标准
        $comboVal = Db::name('config')->where(['name' => 'oncepay'])->column('value');
        
        $res['data']['zifei'] = isset($comboVal[0]) ? $comboVal[0] : 0;
        $res['data']['times'] = 1;
        # 两者都没有的情况, 需要单次付费
        if (!$userHasCombo && !$userHasFree) {
            $res['code'] = 0;
            $res['data']['is_used'] = 0;
            
            exit(json_encode($res, JSON_UNESCAPED_UNICODE));
        }
        # 只有有一种场景, 都可以满足
        $res['code'] = 0;
        $res['data']['is_used'] = 1;
        exit(json_encode($res, JSON_UNESCAPED_UNICODE));        
    }
    /**
     * 获取用户是否有套餐次数 
     */
    private function v2getUserHasCombo($userPhone = '', $comboType = 1)
    {
        # 查看当前用户是否有套餐
        $comboInfo = Db::name('member')->field('id,once_nums,month_day')->where(['phone' => $userPhone])->find();
        
        if ($comboInfo['once_nums'] <= 0 && $comboInfo['month_day'] <= 0)   return false;
        
        # $comboInfo = Db::name('zifei_combo')->field('id,combo_day,add_time')->where(['user_phone' => $userPhone, 'combo_type' => $comboType])->find();
        # # 比对 套餐过期时间
        # $endTimestamp = strtotime($comboInfo['add_time']) + $comboInfo['combo_day']*3600*24;
        # if (time() > $endTimestamp) return false;
        
        return true;
    }
    /**
     * 获取当前用户是否有免费次数 
     */
    private function v2getUserHasFree($userPhone = '')
    {
        $createTimeStart = date('Y-m-d')." 00:00:00";
        $createTimeEnd = date('Y-m-d')." 23:59:59";
        $useCon[] = ['user_phone', '=', $userPhone];
        $useCon[] = ['add_time', 'between time', [$createTimeStart, $createTimeEnd]];
        
        $dailyFreeNum = env('app.userFreeNum', 1);
        $countRes = Db::name('new_user_question_history')->where($useCon)->count();
        
        if ($countRes >= $dailyFreeNum) return false;
        
        return true;
    }
    
}